import json
import logging
import os
import time
from datetime import datetime

from flask import request

logger = logging.getLogger(__name__)


def get_uuid():
    """
    随机生成uuid
    :return: 生成好的uuid
    """
    import uuid
    return str(uuid.uuid4()).replace('-', '')


# 封装一下关于记录序号的日志记录用于全链路的日志请求的日志
def trace_add_log_record(event_des=0, msg_dict={}, remarks=''):
    '''

    :param event_des: 日志记录事件描述
    :param msg_dict: 日志记录信息字典
    :param remarks: 日志备注信息
    :return:
    '''
    if event_des == 0:
        logger.info("----------请求开始-----------")
        logger.info("请求参数为:{}".format(json.dumps(msg_dict)))
    elif event_des == 1:
        logger.info("请求返回结果为:{0},总耗时为:{1}".format(msg_dict.get('rsp_data'), msg_dict.get('cost_time')))
        logger.info("----------请求结束-----------")


def trace_start_log_record_handler():
    '''
    请求记录初始化
    :return:
    '''
    path_info = request.environ.get("PATH_INFO")
    if 'js' in path_info:
        return None
    if path_info == '/':
        return None
    if 'css' in path_info:
        return None
    if 'static' in path_info:
        return None
    if path_info not in ['/favicon.ico'] and 'websocket' not in path_info:
        if request.method != 'OPTIONS':
            # 追踪索引
            request.trace_links_index = 0
            # 追踪ID
            request.traceid = get_uuid()
            # 计算时间
            request.request_start_time = time.time()
            request.request_time = lambda: "%.5f" % (time.time() - request.request_start_time)
            log_msg = {
                # 'headers': str(request.headers),
                # 'user_agent': str(request.user_agent),
                # 记录请求头信息
                # 'headers': request.headers if str(request.headers) else '',
                # 记录请求URL信息
                'url': request.url,
                # 记录请求方法
                'method': request.method,
                # 记录请求来源IP
                # 'ip': request.remote_addr if not request.headers.get("X-Real-IP") else request.headers.get("X-Real-IP"),
                'path': request.path,
                # 记录请求提交的参数信息
                'params': {
                    'args': '' if not request.args else request.args,
                    'form': '' if not request.form else request.form,
                    # 'json': '' if not request.json else request.json,
                    'json': '' if not request.get_json(silent=True) else None,
                },
                # 记录请求的开始时间
                'start_time': str(datetime.fromtimestamp(request.request_start_time)),
            }

            # 执行写入--日志具体的内容信息
            trace_add_log_record(event_des=0, msg_dict=log_msg)


def trace_end_log_record_handler(response):
    # 日志记录----对于找不到的请求地址不做记录信息
    if response.status_code != 200:
        return None
    # 过滤不必要的请求URL
    path_info = request.environ.get("PATH_INFO")
    if path_info == '/':
        return None
    if path_info not in ['/favicon.ico'] and 'websocket' not in path_info:
        if request.method != 'OPTIONS':
            if not response.is_json:
                return None

            def json_loads_responsedata():
                try:
                    # 保持中文的输出
                    # json.loads()是将一个JSON编码的字符串（字典形式）转换为一个Python数据结构
                    new_dict = str(response.data, 'UTF-8')
                    # new_dict = json.dumps(response.data)  # 主要是读json文件时，需要用到
                except:
                    # 输出中文的编码
                    new_dict = str(response.data, encoding='utf-8')
                return new_dict

            # link_add_log_record(event_des='请求结束')
            request.request_time = (float("%.2f" % (time.time() - request.request_start_time)) * 1000) + 5
            log_msg = {
                # 记录请求耗时
                'cost_time': str(request.request_time) + 'ms',
                #  记录请求响应的最终报文信息
                'rsp_data': json_loads_responsedata()
            }
            trace_add_log_record(event_des=1, msg_dict=log_msg)


# 链路追踪中间件
class MiddlewareTraceLogger():

    def __init__(self, *args, **kwargs):
        pass

    def init_app(self, app, _is_handlers_aout=True):
        self.app = app
        if _is_handlers_aout:
            self.register_handlers()
        return self

    def __before_request(self):
        # print('MiddlewareTraceLogger-----before_request')
        # 追踪日志初始化
        trace_start_log_record_handler()

    def __after_request(self, response):
        # 追踪日志收尾
        trace_end_log_record_handler(response)
        return response

    def teardown_request(self, exc):
        '''
        请求结束的时候提交相关的日志
        :param exc:
        :return:
        '''
        pass

    def register_handlers(self):
        self.app.before_request(self.__before_request)
        self.app.after_request(self.__after_request)
        self.app.teardown_request(self.teardown_request)
